﻿<template>
  <div :class="{ 'product-upload': true, 'grid-mutiple': max > 1, 'grid-single': max === 1 }">
    <el-upload
      ref="uploadRef"
      action="#"
      :auto-upload="false"
      :show-file-list="false"
      :on-change="handleBeforeUpload"
      :accept="currentAcceptType"
      v-if="modelValue?.length < max"
      v-loading="uplodLoading"
    >
      <div class="upload-btn">
        <base-icon
          :name="uploadType === 'image' ? 'iconfont ic-zhaoxiangji' : 'iconfont ic-shipin'"
          :size="uploadType === 'image' ? 32 : 26"
          :color="'var(--bd7)'"
        />
        <div class="upload-btn-text">{{ uploadText }}</div>
      </div>
    </el-upload>
    <div class="product-upload-file" v-for="(item, index) in modelValue" :key="index">
      <div class="file-del" @click="handleFileDel(index)">
        <base-icon name="iconfont ic-cuowu" :size="16" :color="'var(--ct2)'" />
      </div>
      <!-- 图片 -->
      <el-image
        v-if="uploadType === 'image'"
        style="width: 120px; height: 120px"
        :src="item"
        :zoom-rate="1.2"
        :max-scale="7"
        :min-scale="0.2"
        :preview-src-list="modelValue"
        show-progress
        :preview-teleported="true"
        fit="cover"
      />
      <!-- 视频 -->
      <div class="product-upload-file-video" v-else>
        <!-- 封面图片 -->
        <img class="cover-img" :src="coverImg" />
        <!-- 播放按钮 -->
        <img class="play-icon" src="@/assets/product/icon-play.png" @click="openPlayModal(item)" />
      </div>
    </div>
    <base-dialog v-model="playVisble" title="查看视频" width="500" :show-footer="false" destroy-on-close>
      <video width="100%" height="450" controls>
        <source :src="videoSourceUrl" />
      </video>
    </base-dialog>
  </div>
</template>

<script setup>
  const props = defineProps({
    // 上传按钮文字
    uploadText: { type: String, default: "上传图片" },
    // 最大上传数量
    max: { type: Number, default: 1 },
    // 上传文件类别
    uploadType: { type: String, default: "image" },
    // 文件列表
    modelValue: {
      type: Array,
      default: () => {
        return [];
      },
    },
  });
  const emit = defineEmits(["update:modelValue"]);
  // 上传Ref
  const uploadRef = ref();
  // 视频格式
  const videoMimeTypes = [
    "video/mp4",
    "video/webm",
    "video/ogg",
    "video/quicktime",
    "video/x-msvideo",
    "video/x-ms-wmv",
    "video/x-flv",
    "video/x-matroska",
  ];
  // 封面图片
  const coverImg = ref("");
  // 当前上传类别
  const currentAcceptType = ref("");
  // 上传loading
  const uplodLoading = ref(false);
  // 当前播放视频
  const videoSourceUrl = ref("");
  // 视频弹窗
  const playVisble = ref(false);
  // 初始化
  onMounted(() => {
    if (props.uploadType === "video") {
      currentAcceptType.value = videoMimeTypes.join(",");
    } else {
      currentAcceptType.value = ".png,.jpeg,.jpg";
    }
  });
  // 上传前处理
  const handleBeforeUpload = rawFile => {
    if (props.uploadType === "image" && !["image/png", "image/jpeg", "image/jpg"].includes(rawFile.raw.type)) {
      $msg.error("请上传jpeg/jpg/png格式图片");
      return false;
    }
    if (props.uploadType === "video" && !videoMimeTypes.includes(rawFile.raw.type)) {
      $msg.error("请上传正确的视频格式文件");
      return false;
    }
    if (props.uploadType === "image" && rawFile.raw.size / 1024 / 1024 > 10) {
      $msg.error("图片最大不超过10MB!");
      return false;
    }
    if (props.uploadType === "video" && rawFile.raw.size / 1024 / 1024 > 10) {
      $msg.error("视频最大不超过10MB!");
      return false;
    }
    handleUpload(rawFile.raw);
    return true;
  };
  // 文件上传
  const handleUpload = file => {
    const formData = new FormData();
    formData.append("file", file);
    uplodLoading.value = true;
    Api.common.fileUpload(formData, { fileType: props.uploadType === "video" ? "02" : "01" }).then(res => {
      if (props.uploadType === "video") {
        getVideoFirstFrame(res.data);
        return;
      }
      uplodLoading.value = false;
      const list = props.modelValue;
      list.push(res.data);
      $msg.success("上传成功!");
      emit("update:modelValue", list);
    });
  };
  // 删除
  const handleFileDel = idx => {
    const list = props.modelValue;
    list.splice(idx, 1);
    if (props.uploadType === "video") {
      coverImg.value = "";
    }
    emit("update:modelValue", list);
  };
  // 获取视频第一帧
  const getVideoFirstFrame = (url, file) => {
    const video = document.createElement("video"); // 创建video对象
    video.src = url; // url地址
    const canvas = document.createElement("canvas"); // 创建 canvas 对象
    const ctx = canvas.getContext("2d"); // 绘制2d
    video.crossOrigin = "anonymous"; // 解决跨域问题，也就是提示污染资源无法转换视频
    video.currentTime = 1; // 第一秒帧
    video.oncanplay = () => {
      canvas.width = 120;
      canvas.height = 120;
      // 利用canvas对象方法绘图
      ctx.drawImage(video, 0, 0, 120, 120);
      const list = props.modelValue;
      // const videoItem = { coverImg: canvas.toDataURL("image/png") };
      coverImg.value = canvas.toDataURL("image/png");
      uplodLoading.value = false;
      list.push(url);
      emit("update:modelValue", list);
      // 转换成base64形式
      // Vue.set(file, 'imageShow', canvas.toDataURL('image/png')) // 获取视频第一帧作为imageShow展示
    };
  };
  // 打开视频播放弹窗
  const openPlayModal = url => {
    videoSourceUrl.value = url;
    playVisble.value = true;
  };
</script>

<style lang="scss" scoped>
  .product-upload {
    display: grid;
    .product-upload-file {
      position: relative;
      width: 120px;
      height: 120px;
      border: 1px solid var(--cb1);
      border-radius: 8px;
      overflow: hidden;
      display: flex;
      justify-content: center;
      .product-upload-file-video {
        width: 100%;
        position: relative;
        .cover-img {
          width: 100%;
        }
        .play-icon {
          width: 40px;
          height: 40px;
          position: absolute;
          top: 40px;
          left: 40px;
          cursor: pointer;
        }
      }
      .file-del {
        position: absolute;
        top: 0px;
        right: 5px;
        cursor: pointer;
        z-index: 2;
      }
    }
    .upload-btn {
      width: 120px;
      height: 120px;
      display: flex;
      align-items: center;
      justify-content: center;
      align-content: center;
      flex-wrap: wrap;
      border: 1px dashed var(--cb1);
      border-radius: 8px;
      .upload-btn-text {
        width: 100%;
        text-align: center;
        font-size: 12px;
        color: var(--ct2);
      }
    }
  }
  .grid-mutiple {
    grid-template-columns: repeat(5, 120px);
    column-gap: 8px;
    row-gap: 8px;
  }
  .grid-single {
    grid-template-columns: repeat(1, 120px);
  }
</style>
